package bookhive.client;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;

import org.jopac2.jbal.RecordFactory;
import org.jopac2.jbal.RecordInterface;
import org.jopac2.utils.BookSignature;
import org.jopac2.utils.JOpac2Exception;

import net.jxta.exception.PeerGroupException;
import net.jxta.peergroup.PeerGroup;

import bookhive.PeerLauncher;
import bookhive.datastructures.catalog.CatalogGroupInfo;
import bookhive.datastructures.datasource.DataItem;
import bookhive.datastructures.datasource.HashItem;

public class ClientLauncher extends PeerLauncher {

	private ResultListener resultListener;

	private TreeMap<String, ClientPeer> clients;

	public ClientLauncher(ResultListener rl) {
		super(new File("config/clientcatalog.config"));
		resultListener = rl;
		clients = new TreeMap<String, ClientPeer>();
	}

	public ClientLauncher(ResultListener rl, TreeSet<CatalogGroupInfo> groups) {
		super(groups);
		resultListener = rl;
		clients = new TreeMap<String, ClientPeer>();
	}

	public void start() {

		HttpTcpConfig();

		Iterator<CatalogGroupInfo> groups = catalogGroups.iterator();
		while (groups.hasNext()) {
			String groupName = groups.next().getName();
			createClientInGroup(groupName);
		}
	}

	private void HttpTcpConfig() {
		try {
			manager.getConfigurator().setHttpEnabled(true);
			manager.getConfigurator().setHttpIncoming(false);
			manager.getConfigurator().setHttpOutgoing(true);
			manager.getConfigurator().setTcpEnabled(true);
			manager.getConfigurator().setTcpIncoming(false);
			manager.getConfigurator().setTcpOutgoing(true);
			manager.startNetwork();
		} catch (IOException e1) {
			e1.printStackTrace();
		} catch (PeerGroupException e) {
			e.printStackTrace();
		}
	}

	public boolean createClientInGroup(String groupName) {
		return createClientInGroup(new CatalogGroupInfo(groupName));
	}

	public boolean createClientInGroup(CatalogGroupInfo gInfo) {

		Iterator<URI> rdvs = gInfo.getSuperNodes().iterator();
		while (rdvs.hasNext()) {
			URI rdv = rdvs.next();
			if (rdv != null)
				try {
					manager.getConfigurator().addSeedRendezvous(rdv);
					manager.getConfigurator().addSeedRelay(rdv);
				} catch (IOException e) {
					e.printStackTrace();
				}
		}

		manager.waitForRendezvousConnection(10000);

		try {
			System.out.println("Trying joinGroupIfExists(groupName);");
			PeerGroup pg = joinGroupIfExists(gInfo);
			if (pg == null) {
				System.out.println("Group not found");
				return false;
			}

			ClientPeer c = new ClientPeer(pg, resultListener);
			if (c == null)
				return false;
			c.setCatalogProperties(catalogProps);
			c.start();
			clients.put(gInfo.getName(), c);

		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public ClientPeer getClientForPeerGroup(String groupname) {
		return clients.get(groupname);
	}

	/**
	 * Qs main non viene mai usato, solo per debugging
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		ClientLauncher cl = new ClientLauncher(null);
		cl.start();

		ClientPeer cp = cl.getClientForPeerGroup("Universal-CatalogGroup");
		for (int jid = 0; jid < 1; jid++) {
			cp.sendHashQuery("AUT=manzoni");

			while (cp.currentHashResults.size() < 1) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			Iterator<HashItem> hashiter = cp.currentHashResults.iterator();

			while (hashiter.hasNext()) {
				HashItem hi = hashiter.next();

				TreeSet<String> ts = new TreeSet<String>();
				ts.add(hi.hash);
				System.out.println("Looking for data for hash: " + hi.hash);

				cp.sendDataQuery(ts);

				while (cp.currentDataResults.size() < 1) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println("Found " + cp.currentDataResults.size()
						+ " records with hash " + hi.hash);
				DataItem di = cp.currentDataResults.first();

				boolean modif = false;

				RecordInterface ri = RecordFactory.buildRecord(di.id, di.data,
						di.type, 0);

				// System.out.println(ri.toString());

				Iterator<BookSignature> bsIter = hi.signs.iterator();
				while (bsIter.hasNext()) {
					BookSignature bs = bsIter.next();
					try {
						if (ri.getSignatures().contains(bs))
							continue;
						ri.addSignature(bs);
						modif = true;

					} catch (JOpac2Exception e) {
						e.printStackTrace();
					}
				}
				if (modif) {
					Vector<RecordInterface> ris = new Vector<RecordInterface>();
					ris.add(ri);
					cp.sendUpdate(ris);
				}

			}
		}

	}

}
